/****************************************************************
 * Fulguro
 * Copyright (C) 2004 Christophe Clienti
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 ***************************************************************/


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <flgrCoreIO.h>
#include <flgrCoreData.h>
#include <flgrCoreDataIO.h>
#include <flgrCoreDispatch.h>
#include "flgrMorphoDistanceFast.h"


//////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////
#define FLGR_MACRO_FAST_RASTER_DISTANCE_8(dtype)			\
  int i,j;								\
  int k,l,n;								\
  int sx = dat->size_x;							\
  int sy = dat->size_y;							\
  dtype **pdat=(dtype **) dat->array;					\
  dtype minval;								\
  dtype valpix;								\
									\
  /* pixel [0,0] */							\
  minval = flgr2d_get_data_array_##dtype(pdat,0,0);			\
									\
  /* pixels [0, 1..size_x-1] */						\
  for(j=1 ; j<sx-1 ; j++) {						\
    valpix = flgr2d_get_data_array_##dtype(pdat,0,j);			\
    minval = (valpix == 0) ? 0 : (FLGR_MIN(minval+1,valpix));		\
    flgr2d_set_data_array_##dtype(pdat,0,j,minval);			\
  }									\
									\
									\
  for(i=1,k=0 ; i<sy ; i++,k++) {					\
    /* pixel [1..size_y-1, 0] */					\
    minval = flgr2d_get_data_array_##dtype(pdat,k,0);			\
    valpix = flgr2d_get_data_array_##dtype(pdat,k,1);			\
    minval = FLGR_MIN(valpix,minval);					\
    valpix = flgr2d_get_data_array_##dtype(pdat,i,0);			\
    minval = (valpix == 0) ? 0 : (FLGR_MIN(minval+1,valpix));		\
    flgr2d_set_data_array_##dtype(pdat,i,0,minval);			\
									\
    /* pixel [1..size_y-1, 1..size_x-2] */				\
    for(l=0,j=1,n=2 ; j<sx-1 ; j++,l++,n++) {				\
      valpix = flgr2d_get_data_array_##dtype(pdat,k,l);			\
      minval = FLGR_MIN(valpix,minval);					\
      valpix = flgr2d_get_data_array_##dtype(pdat,k,j);			\
      minval = FLGR_MIN(valpix,minval);					\
      valpix = flgr2d_get_data_array_##dtype(pdat,k,n);			\
      minval = FLGR_MIN(valpix,minval);					\
      valpix = flgr2d_get_data_array_##dtype(pdat,i,j);			\
      minval = (valpix == 0) ? 0 : (FLGR_MIN(minval+1,valpix));		\
      flgr2d_set_data_array_##dtype(pdat,i,j,minval);			\
    }									\
									\
    /* pixel [1..size_y-1, size_x-1] */					\
    valpix = flgr2d_get_data_array_##dtype(pdat,k,sx-1);		\
    minval = FLGR_MIN(valpix,minval);					\
    valpix = flgr2d_get_data_array_##dtype(pdat,k,sx-2);		\
    minval = FLGR_MIN(valpix,minval);					\
    valpix = flgr2d_get_data_array_##dtype(pdat,i,j);			\
    minval = (valpix == 0) ? 0 : (FLGR_MIN(minval+1,valpix));		\
    flgr2d_set_data_array_##dtype(pdat,i,sx-1,minval);			\
									\
									\
  }									\
									\
  return

void flgr2d_distance_raster_8_connexity_fgUINT8(FLGR_Data2D *dat) {
  FLGR_MACRO_FAST_RASTER_DISTANCE_8(fgUINT8);
}
void flgr2d_distance_raster_8_connexity_fgUINT16(FLGR_Data2D *dat) {
  FLGR_MACRO_FAST_RASTER_DISTANCE_8(fgUINT16);
}
void flgr2d_distance_raster_8_connexity_fgUINT32(FLGR_Data2D *dat) {
  FLGR_MACRO_FAST_RASTER_DISTANCE_8(fgUINT32);
}
void flgr2d_distance_raster_8_connexity_fgINT8(FLGR_Data2D *dat) {
  FLGR_MACRO_FAST_RASTER_DISTANCE_8(fgINT8);
}
void flgr2d_distance_raster_8_connexity_fgINT16(FLGR_Data2D *dat) {
  FLGR_MACRO_FAST_RASTER_DISTANCE_8(fgINT16);
}
void flgr2d_distance_raster_8_connexity_fgINT32(FLGR_Data2D *dat) {
  FLGR_MACRO_FAST_RASTER_DISTANCE_8(fgINT32);
}
void flgr2d_distance_raster_8_connexity_fgFLOAT32(FLGR_Data2D *dat) {
  FLGR_MACRO_FAST_RASTER_DISTANCE_8(fgFLOAT32);
}
void flgr2d_distance_raster_8_connexity_fgFLOAT64(FLGR_Data2D *dat) {
  FLGR_MACRO_FAST_RASTER_DISTANCE_8(fgFLOAT64);
}




//////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////
#define FLGR_MACRO_FAST_ANTIRASTER_DISTANCE_8(dtype)			\
  int i,j;								\
  int k,l,n;								\
  int sx = dat->size_x;							\
  int sy = dat->size_y;							\
  dtype **pdat=(dtype **) dat->array;					\
  dtype minval;								\
  dtype valpix;								\
									\
  /* pixel [size_y-1,size_x-1] */					\
  minval = flgr2d_get_data_array_##dtype(pdat,sy-1,sx-1);		\
									\
  /* pixels [size_y-1, size_x-2..0] */					\
  for(j=sx-2 ; j>=0 ; j--) {						\
    valpix = flgr2d_get_data_array_##dtype(pdat,sy-1,j);		\
    minval = (valpix == 0) ? 0 : (FLGR_MIN(minval+1,valpix));		\
    flgr2d_set_data_array_##dtype(pdat,sy-1,j,minval);			\
  }									\
									\
									\
  for(i=sy-2,k=sy-1 ; i>=0 ; i--,k--) {					\
    /* pixel [size_y-2..0, size_x-1] */					\
    minval = flgr2d_get_data_array_##dtype(pdat,k,sx-1);		\
    valpix = flgr2d_get_data_array_##dtype(pdat,k,sx-2);		\
    minval = FLGR_MIN(valpix,minval);					\
    valpix = flgr2d_get_data_array_##dtype(pdat,i,sx-1);		\
    minval = (valpix == 0) ? 0 : (FLGR_MIN(minval+1,valpix));		\
    flgr2d_set_data_array_##dtype(pdat,i,sx-1,minval);			\
									\
    /* pixel [size_y-2..0, size_x-2..1] */				\
    for(l=sx-3,j=sx-2,n=sx-1 ; j>=1 ; j--,l--,n--) {			\
      valpix = flgr2d_get_data_array_##dtype(pdat,k,l);			\
      minval = FLGR_MIN(valpix,minval);					\
      valpix = flgr2d_get_data_array_##dtype(pdat,k,j);			\
      minval = FLGR_MIN(valpix,minval);					\
      valpix = flgr2d_get_data_array_##dtype(pdat,k,n);			\
      minval = FLGR_MIN(valpix,minval);					\
      valpix = flgr2d_get_data_array_##dtype(pdat,i,j);			\
      minval = (valpix == 0) ? 0 : (FLGR_MIN(minval+1,valpix));		\
      flgr2d_set_data_array_##dtype(pdat,i,j,minval);			\
    }									\
									\
    /* pixel [1..size_y-1, size_x-1] */					\
    valpix = flgr2d_get_data_array_##dtype(pdat,k,0);			\
    minval = FLGR_MIN(valpix,minval);					\
    valpix = flgr2d_get_data_array_##dtype(pdat,k,1);			\
    minval = FLGR_MIN(valpix,minval);					\
    valpix = flgr2d_get_data_array_##dtype(pdat,i,0);			\
    minval = (valpix == 0) ? 0 : (FLGR_MIN(minval+1,valpix));		\
    flgr2d_set_data_array_##dtype(pdat,i,0,minval);			\
									\
									\
  }									\
									\
  return


void flgr2d_distance_antiraster_8_connexity_fgUINT8(FLGR_Data2D *dat) {
  FLGR_MACRO_FAST_ANTIRASTER_DISTANCE_8(fgUINT8);
}
void flgr2d_distance_antiraster_8_connexity_fgUINT16(FLGR_Data2D *dat) {
  FLGR_MACRO_FAST_ANTIRASTER_DISTANCE_8(fgUINT16);
}
void flgr2d_distance_antiraster_8_connexity_fgUINT32(FLGR_Data2D *dat) {
  FLGR_MACRO_FAST_ANTIRASTER_DISTANCE_8(fgUINT32);
}
void flgr2d_distance_antiraster_8_connexity_fgINT8(FLGR_Data2D *dat) {
  FLGR_MACRO_FAST_ANTIRASTER_DISTANCE_8(fgINT8);
}
void flgr2d_distance_antiraster_8_connexity_fgINT16(FLGR_Data2D *dat) {
  FLGR_MACRO_FAST_ANTIRASTER_DISTANCE_8(fgINT16);
}
void flgr2d_distance_antiraster_8_connexity_fgINT32(FLGR_Data2D *dat) {
  FLGR_MACRO_FAST_ANTIRASTER_DISTANCE_8(fgINT32);
}
void flgr2d_distance_antiraster_8_connexity_fgFLOAT32(FLGR_Data2D *dat) {
  FLGR_MACRO_FAST_ANTIRASTER_DISTANCE_8(fgFLOAT32);
}
void flgr2d_distance_antiraster_8_connexity_fgFLOAT64(FLGR_Data2D *dat) {
  FLGR_MACRO_FAST_ANTIRASTER_DISTANCE_8(fgFLOAT64);
}














//////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////
#define FLGR_MACRO_FAST_RASTER_DISTANCE_6(dtype)			\
  int i,j;								\
  int k,l,n;								\
  int sx = dat->size_x;							\
  int sy = dat->size_y;							\
  dtype **pdat=(dtype **) dat->array;					\
  dtype minval;								\
  dtype valpix;								\
									\
  /* pixel [0,0] */							\
  minval = flgr2d_get_data_array_##dtype(pdat,0,0);			\
									\
  /* pixels [0, 1..size_x-1] */						\
  for(j=1 ; j<sx-1 ; j++) {						\
    valpix = flgr2d_get_data_array_##dtype(pdat,0,j);			\
    minval = (valpix == 0) ? 0 : (FLGR_MIN(minval+1,valpix));		\
    flgr2d_set_data_array_##dtype(pdat,0,j,minval);			\
  }									\
									\
									\
  for(i=1,k=0 ; i<sy-1 ; i+=2,k+=2) {					\
    /*********************/						\
    /******** ODD ********/						\
    /*********************/						\
    /* pixel [1..size_y-1, 0] */					\
    minval = flgr2d_get_data_array_##dtype(pdat,k,0);			\
    valpix = flgr2d_get_data_array_##dtype(pdat,i,0);			\
    minval = (valpix == 0) ? 0 : (FLGR_MIN(minval+1,valpix));		\
    flgr2d_set_data_array_##dtype(pdat,i,0,minval);			\
									\
    /* pixel [1..size_y-1, 1..size_x-1] */				\
    for(l=0,j=1 ; j<sx ; j++,l++) {					\
      valpix = flgr2d_get_data_array_##dtype(pdat,k,l);			\
      minval = FLGR_MIN(valpix,minval);					\
      valpix = flgr2d_get_data_array_##dtype(pdat,k,j);			\
      minval = FLGR_MIN(valpix,minval);					\
      valpix = flgr2d_get_data_array_##dtype(pdat,i,j);			\
      minval = (valpix == 0) ? 0 : (FLGR_MIN(minval+1,valpix));		\
      flgr2d_set_data_array_##dtype(pdat,i,j,minval);			\
    }									\
									\
    /*********************/						\
    /******* EVEN ********/						\
    /*********************/						\
    minval = flgr2d_get_data_array_##dtype(pdat,i,0);			\
    valpix = flgr2d_get_data_array_##dtype(pdat,i,1);			\
    minval = FLGR_MIN(valpix,minval);					\
    valpix = flgr2d_get_data_array_##dtype(pdat,i+1,0);			\
    minval = (valpix == 0) ? 0 : (FLGR_MIN(minval+1,valpix));		\
    flgr2d_set_data_array_##dtype(pdat,i+1,0,minval);			\
									\
    /* pixel [1..size_y-1, 1..size_x-2] */				\
    for(j=1,n=2 ; j<sx-1 ; j++,n++) {					\
      valpix = flgr2d_get_data_array_##dtype(pdat,i,j);			\
      minval = FLGR_MIN(valpix,minval);					\
      valpix = flgr2d_get_data_array_##dtype(pdat,i,n);			\
      minval = FLGR_MIN(valpix,minval);					\
      valpix = flgr2d_get_data_array_##dtype(pdat,i+1,j);		\
      minval = (valpix == 0) ? 0 : (FLGR_MIN(minval+1,valpix));		\
      flgr2d_set_data_array_##dtype(pdat,i+1,j,minval);			\
    }									\
									\
    /* pixel [1..size_y-1, size_x-1] */					\
    valpix = flgr2d_get_data_array_##dtype(pdat,i,sx-1);		\
    minval = FLGR_MIN(valpix,minval);					\
    valpix = flgr2d_get_data_array_##dtype(pdat,i+1,j);			\
    minval = (valpix == 0) ? 0 : (FLGR_MIN(minval+1,valpix));		\
    flgr2d_set_data_array_##dtype(pdat,i+1,sx-1,minval);		\
									\
  }									\
									\
  if((sy%2)==0) {							\
    /*********************/						\
    /******** ODD ********/						\
    /*********************/						\
    i = sy-1;								\
    k = sy-2;								\
									\
    minval = flgr2d_get_data_array_##dtype(pdat,k,0);			\
    valpix = flgr2d_get_data_array_##dtype(pdat,i,0);			\
    minval = (valpix == 0) ? 0 : (FLGR_MIN(minval+1,valpix));		\
    flgr2d_set_data_array_##dtype(pdat,i,0,minval);			\
									\
    /* pixel [1..size_y-1, 1..size_x-1] */				\
    for(l=0,j=1 ; j<sx ; j++,l++) {					\
      valpix = flgr2d_get_data_array_##dtype(pdat,k,l);			\
      minval = FLGR_MIN(valpix,minval);					\
      valpix = flgr2d_get_data_array_##dtype(pdat,k,j);			\
      minval = FLGR_MIN(valpix,minval);					\
      valpix = flgr2d_get_data_array_##dtype(pdat,i,j);			\
      minval = (valpix == 0) ? 0 : (FLGR_MIN(minval+1,valpix));		\
      flgr2d_set_data_array_##dtype(pdat,i,j,minval);			\
    }									\
									\
  }									\
									\
  return

void flgr2d_distance_raster_6_connexity_fgUINT8(FLGR_Data2D *dat) {
  FLGR_MACRO_FAST_RASTER_DISTANCE_6(fgUINT8);
}
void flgr2d_distance_raster_6_connexity_fgUINT16(FLGR_Data2D *dat) {
  FLGR_MACRO_FAST_RASTER_DISTANCE_6(fgUINT16);
}
void flgr2d_distance_raster_6_connexity_fgUINT32(FLGR_Data2D *dat) {
  FLGR_MACRO_FAST_RASTER_DISTANCE_6(fgUINT32);
}
void flgr2d_distance_raster_6_connexity_fgINT8(FLGR_Data2D *dat) {
  FLGR_MACRO_FAST_RASTER_DISTANCE_6(fgINT8);
}
void flgr2d_distance_raster_6_connexity_fgINT16(FLGR_Data2D *dat) {
  FLGR_MACRO_FAST_RASTER_DISTANCE_6(fgINT16);
}
void flgr2d_distance_raster_6_connexity_fgINT32(FLGR_Data2D *dat) {
  FLGR_MACRO_FAST_RASTER_DISTANCE_6(fgINT32);
}
void flgr2d_distance_raster_6_connexity_fgFLOAT32(FLGR_Data2D *dat) {
  FLGR_MACRO_FAST_RASTER_DISTANCE_6(fgFLOAT32);
}
void flgr2d_distance_raster_6_connexity_fgFLOAT64(FLGR_Data2D *dat) {
  FLGR_MACRO_FAST_RASTER_DISTANCE_6(fgFLOAT64);
}




//////////////////////////////////////////////////////////////////
// Warning need to swap odd and even se for antiraster scan in 6 connexity
//////////////////////////////////////////////////////////////////
#define FLGR_MACRO_FAST_ANTIRASTER_DISTANCE_6(dtype)			\
  int i,j;								\
  int k,l,n;								\
  int istart;								\
  int sx = dat->size_x;							\
  int sy = dat->size_y;							\
  dtype **pdat=(dtype **) dat->array;					\
  dtype minval;								\
  dtype valpix;								\
  									\
  /* pixel [size_y-1,size_x-1] */					\
  minval = flgr2d_get_data_array_##dtype(pdat,sy-1,sx-1);		\
  									\
									\
  if((sy%2)==0) {							\
    /*********************/						\
    /******** ODD ********/						\
    /*********************/						\
    i = sy-1;								\
    									\
    for(j=sx-2 ; j>=0 ; j--) {						\
      valpix = flgr2d_get_data_array_##dtype(pdat,i,j);			\
      minval = (valpix == 0) ? 0 : (FLGR_MIN(minval+1,valpix));		\
      flgr2d_set_data_array_##dtype(pdat,i,j,minval);			\
    }									\
    									\
    /*********************/						\
    /******* EVEN ********/						\
    /*********************/						\
    k = i--;								\
    									\
    minval = flgr2d_get_data_array_##dtype(pdat,k,sx-1);		\
    valpix = flgr2d_get_data_array_##dtype(pdat,i,sx-1);		\
    minval = (valpix == 0) ? 0 : (FLGR_MIN(minval+1,valpix));		\
    flgr2d_set_data_array_##dtype(pdat,i,sx-1,minval);			\
    									\
    for(l=sx-1,j=sx-2 ; j>=0 ; j--,l--) {				\
      valpix = flgr2d_get_data_array_##dtype(pdat,k,l);			\
      minval = FLGR_MIN(valpix,minval);					\
      valpix = flgr2d_get_data_array_##dtype(pdat,k,j);			\
      minval = FLGR_MIN(valpix,minval);					\
      valpix = flgr2d_get_data_array_##dtype(pdat,i,j);			\
      minval = (valpix == 0) ? 0 : (FLGR_MIN(minval+1,valpix));		\
      flgr2d_set_data_array_##dtype(pdat,i,j,minval);			\
    }									\
    									\
    istart = sy-3;							\
    									\
  }else {								\
    /*********************/						\
    /******* EVEN ********/						\
    /*********************/						\
    i = sy-1;								\
									\
    for(j=sx-2 ; j>=0 ; j--) {						\
      valpix = flgr2d_get_data_array_##dtype(pdat,i,j);			\
      minval = (valpix == 0) ? 0 : (FLGR_MIN(minval+1,valpix));		\
      flgr2d_set_data_array_##dtype(pdat,i,j,minval);			\
    }									\
									\
    istart = sy-2;							\
									\
  }									\
  									\
  for(i=istart,k=istart+1 ; i>=0 ; i-=2,k-=2) {				\
    /*********************/						\
    /******** ODD ********/						\
    /*********************/						\
    /* pixel [size_y-2..0, size_x-1] */					\
    minval = flgr2d_get_data_array_##dtype(pdat,k,sx-1);		\
    valpix = flgr2d_get_data_array_##dtype(pdat,k,sx-2);		\
    minval = FLGR_MIN(valpix,minval);					\
    valpix = flgr2d_get_data_array_##dtype(pdat,i,sx-1);		\
    minval = (valpix == 0) ? 0 : (FLGR_MIN(minval+1,valpix));		\
    flgr2d_set_data_array_##dtype(pdat,i,sx-1,minval);			\
									\
    /* pixel [size_y-2..0, size_x-2..1] */				\
    for(l=sx-3,j=sx-2 ; j>=1 ; j--,l--) {				\
      valpix = flgr2d_get_data_array_##dtype(pdat,k,l);			\
      minval = FLGR_MIN(valpix,minval);					\
      valpix = flgr2d_get_data_array_##dtype(pdat,k,j);			\
      minval = FLGR_MIN(valpix,minval);					\
      valpix = flgr2d_get_data_array_##dtype(pdat,i,j);			\
      minval = (valpix == 0) ? 0 : (FLGR_MIN(minval+1,valpix));		\
      flgr2d_set_data_array_##dtype(pdat,i,j,minval);			\
    }									\
									\
    /* pixel [1..size_y-1, size_x-1] */					\
    valpix = flgr2d_get_data_array_##dtype(pdat,k,0);			\
    minval = FLGR_MIN(valpix,minval);					\
    valpix = flgr2d_get_data_array_##dtype(pdat,i,0);			\
    minval = (valpix == 0) ? 0 : (FLGR_MIN(minval+1,valpix));		\
    flgr2d_set_data_array_##dtype(pdat,i,0,minval);			\
									\
    /*********************/						\
    /******* EVEN ********/						\
    /*********************/						\
    /* pixel [size_y-2..0, size_x-1] */					\
    minval = flgr2d_get_data_array_##dtype(pdat,i,sx-1);		\
    valpix = flgr2d_get_data_array_##dtype(pdat,i-1,sx-1);		\
    minval = (valpix == 0) ? 0 : (FLGR_MIN(minval+1,valpix));		\
    flgr2d_set_data_array_##dtype(pdat,i-1,sx-1,minval);		\
									\
    /* pixel [size_y-2..0, size_x-2..1] */				\
    for(j=sx-2,n=sx-1 ; j>=0 ; j--,n--) {				\
      valpix = flgr2d_get_data_array_##dtype(pdat,i,j);			\
      minval = FLGR_MIN(valpix,minval);					\
      valpix = flgr2d_get_data_array_##dtype(pdat,i,n);			\
      minval = FLGR_MIN(valpix,minval);					\
      valpix = flgr2d_get_data_array_##dtype(pdat,i-1,j);		\
      minval = (valpix == 0) ? 0 : (FLGR_MIN(minval+1,valpix));		\
      flgr2d_set_data_array_##dtype(pdat,i-1,j,minval);			\
    }									\
									\
  }									\
									\
  return


void flgr2d_distance_antiraster_6_connexity_fgUINT8(FLGR_Data2D *dat) {
  FLGR_MACRO_FAST_ANTIRASTER_DISTANCE_6(fgUINT8);
}
void flgr2d_distance_antiraster_6_connexity_fgUINT16(FLGR_Data2D *dat) {
  FLGR_MACRO_FAST_ANTIRASTER_DISTANCE_6(fgUINT16);
}
void flgr2d_distance_antiraster_6_connexity_fgUINT32(FLGR_Data2D *dat) {
  FLGR_MACRO_FAST_ANTIRASTER_DISTANCE_6(fgUINT32);
}
void flgr2d_distance_antiraster_6_connexity_fgINT8(FLGR_Data2D *dat) {
  FLGR_MACRO_FAST_ANTIRASTER_DISTANCE_6(fgINT8);
}
void flgr2d_distance_antiraster_6_connexity_fgINT16(FLGR_Data2D *dat) {
  FLGR_MACRO_FAST_ANTIRASTER_DISTANCE_6(fgINT16);
}
void flgr2d_distance_antiraster_6_connexity_fgINT32(FLGR_Data2D *dat) {
  FLGR_MACRO_FAST_ANTIRASTER_DISTANCE_6(fgINT32);
}
void flgr2d_distance_antiraster_6_connexity_fgFLOAT32(FLGR_Data2D *dat) {
  FLGR_MACRO_FAST_ANTIRASTER_DISTANCE_6(fgFLOAT32);
}
void flgr2d_distance_antiraster_6_connexity_fgFLOAT64(FLGR_Data2D *dat) {
  FLGR_MACRO_FAST_ANTIRASTER_DISTANCE_6(fgFLOAT64);
}




















//////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////
#define FLGR_MACRO_FAST_RASTER_DISTANCE_4(dtype)			\
  int i,j;								\
  int k;								\
  int sx = dat->size_x;							\
  int sy = dat->size_y;							\
  dtype **pdat=(dtype **) dat->array;					\
  dtype minval;								\
  dtype valpix;								\
									\
  /* pixel [0,0] */							\
  minval = flgr2d_get_data_array_##dtype(pdat,0,0);			\
									\
  /* pixels [0, 1..size_x-1] */						\
  for(j=1 ; j<sx-1 ; j++) {						\
    valpix = flgr2d_get_data_array_##dtype(pdat,0,j);			\
    minval = (valpix == 0) ? 0 : (FLGR_MIN(minval+1,valpix));		\
    flgr2d_set_data_array_##dtype(pdat,0,j,minval);			\
  }									\
									\
									\
  for(i=1,k=0 ; i<sy ; i++,k++) {					\
    /* pixel [1..size_y-1, 0] */					\
    minval = flgr2d_get_data_array_##dtype(pdat,k,0);			\
    valpix = flgr2d_get_data_array_##dtype(pdat,i,0);			\
    minval = (valpix == 0) ? 0 : (FLGR_MIN(minval+1,valpix));		\
    flgr2d_set_data_array_##dtype(pdat,i,0,minval);			\
									\
    /* pixel [1..size_y-1, 1..size_x-2] */				\
    for(j=1 ; j<sx-1 ; j++) {						\
      valpix = flgr2d_get_data_array_##dtype(pdat,k,j);			\
      minval = FLGR_MIN(valpix,minval);					\
      valpix = flgr2d_get_data_array_##dtype(pdat,i,j);			\
      minval = (valpix == 0) ? 0 : (FLGR_MIN(minval+1,valpix));		\
      flgr2d_set_data_array_##dtype(pdat,i,j,minval);			\
    }									\
									\
    /* pixel [1..size_y-1, size_x-1] */					\
    valpix = flgr2d_get_data_array_##dtype(pdat,k,sx-1);		\
    minval = FLGR_MIN(valpix,minval);					\
    valpix = flgr2d_get_data_array_##dtype(pdat,i,j);			\
    minval = (valpix == 0) ? 0 : (FLGR_MIN(minval+1,valpix));		\
    flgr2d_set_data_array_##dtype(pdat,i,sx-1,minval);			\
									\
									\
  }									\
									\
  return

void flgr2d_distance_raster_4_connexity_fgUINT8(FLGR_Data2D *dat) {
  FLGR_MACRO_FAST_RASTER_DISTANCE_4(fgUINT8);
}
void flgr2d_distance_raster_4_connexity_fgUINT16(FLGR_Data2D *dat) {
  FLGR_MACRO_FAST_RASTER_DISTANCE_4(fgUINT16);
}
void flgr2d_distance_raster_4_connexity_fgUINT32(FLGR_Data2D *dat) {
  FLGR_MACRO_FAST_RASTER_DISTANCE_4(fgUINT32);
}
void flgr2d_distance_raster_4_connexity_fgINT8(FLGR_Data2D *dat) {
  FLGR_MACRO_FAST_RASTER_DISTANCE_4(fgINT8);
}
void flgr2d_distance_raster_4_connexity_fgINT16(FLGR_Data2D *dat) {
  FLGR_MACRO_FAST_RASTER_DISTANCE_4(fgINT16);
}
void flgr2d_distance_raster_4_connexity_fgINT32(FLGR_Data2D *dat) {
  FLGR_MACRO_FAST_RASTER_DISTANCE_4(fgINT32);
}
void flgr2d_distance_raster_4_connexity_fgFLOAT32(FLGR_Data2D *dat) {
  FLGR_MACRO_FAST_RASTER_DISTANCE_4(fgFLOAT32);
}
void flgr2d_distance_raster_4_connexity_fgFLOAT64(FLGR_Data2D *dat) {
  FLGR_MACRO_FAST_RASTER_DISTANCE_4(fgFLOAT64);
}




//////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////
#define FLGR_MACRO_FAST_ANTIRASTER_DISTANCE_4(dtype)			\
  int i,j;								\
  int k;								\
  int sx = dat->size_x;							\
  int sy = dat->size_y;							\
  dtype **pdat=(dtype **) dat->array;					\
  dtype minval;								\
  dtype valpix;								\
									\
  /* pixel [size_y-1,size_x-1] */					\
  minval = flgr2d_get_data_array_##dtype(pdat,sy-1,sx-1);		\
									\
  /* pixels [size_y-1, size_x-2..0] */					\
  for(j=sx-2 ; j>=0 ; j--) {						\
    valpix = flgr2d_get_data_array_##dtype(pdat,sy-1,j);		\
    minval = (valpix == 0) ? 0 : (FLGR_MIN(minval+1,valpix));		\
    flgr2d_set_data_array_##dtype(pdat,sy-1,j,minval);			\
  }									\
									\
									\
  for(i=sy-2,k=sy-1 ; i>=0 ; i--,k--) {					\
    /* pixel [size_y-2..0, size_x-1] */					\
    minval = flgr2d_get_data_array_##dtype(pdat,k,sx-1);		\
    valpix = flgr2d_get_data_array_##dtype(pdat,i,sx-1);		\
    minval = (valpix == 0) ? 0 : (FLGR_MIN(minval+1,valpix));		\
    flgr2d_set_data_array_##dtype(pdat,i,sx-1,minval);			\
									\
    /* pixel [size_y-2..0, size_x-2..1] */				\
    for(j=sx-2 ; j>=1 ; j--) {						\
      valpix = flgr2d_get_data_array_##dtype(pdat,k,j);			\
      minval = FLGR_MIN(valpix,minval);					\
      valpix = flgr2d_get_data_array_##dtype(pdat,i,j);			\
      minval = (valpix == 0) ? 0 : (FLGR_MIN(minval+1,valpix));		\
      flgr2d_set_data_array_##dtype(pdat,i,j,minval);			\
    }									\
									\
    /* pixel [1..size_y-1, size_x-1] */					\
    valpix = flgr2d_get_data_array_##dtype(pdat,k,0);			\
    minval = FLGR_MIN(valpix,minval);					\
    valpix = flgr2d_get_data_array_##dtype(pdat,i,0);			\
    minval = (valpix == 0) ? 0 : (FLGR_MIN(minval+1,valpix));		\
    flgr2d_set_data_array_##dtype(pdat,i,0,minval);			\
									\
									\
  }									\
									\
  return


void flgr2d_distance_antiraster_4_connexity_fgUINT8(FLGR_Data2D *dat) {
  FLGR_MACRO_FAST_ANTIRASTER_DISTANCE_4(fgUINT8);
}
void flgr2d_distance_antiraster_4_connexity_fgUINT16(FLGR_Data2D *dat) {
  FLGR_MACRO_FAST_ANTIRASTER_DISTANCE_4(fgUINT16);
}
void flgr2d_distance_antiraster_4_connexity_fgUINT32(FLGR_Data2D *dat) {
  FLGR_MACRO_FAST_ANTIRASTER_DISTANCE_4(fgUINT32);
}
void flgr2d_distance_antiraster_4_connexity_fgINT8(FLGR_Data2D *dat) {
  FLGR_MACRO_FAST_ANTIRASTER_DISTANCE_4(fgINT8);
}
void flgr2d_distance_antiraster_4_connexity_fgINT16(FLGR_Data2D *dat) {
  FLGR_MACRO_FAST_ANTIRASTER_DISTANCE_4(fgINT16);
}
void flgr2d_distance_antiraster_4_connexity_fgINT32(FLGR_Data2D *dat) {
  FLGR_MACRO_FAST_ANTIRASTER_DISTANCE_4(fgINT32);
}
void flgr2d_distance_antiraster_4_connexity_fgFLOAT32(FLGR_Data2D *dat) {
  FLGR_MACRO_FAST_ANTIRASTER_DISTANCE_4(fgFLOAT32);
}
void flgr2d_distance_antiraster_4_connexity_fgFLOAT64(FLGR_Data2D *dat) {
  FLGR_MACRO_FAST_ANTIRASTER_DISTANCE_4(fgFLOAT64);
}

